Skip to content

fix(ai-amazon-bedrock): emit finish part after metadata event to preserve token usage in streaming - #6160

Closed
jamesone wants to merge 2 commits into
Effect-TS:mainfrom
jamesone:fix/ai-bedrock-streaming-cached-tokens
Closed

fix(ai-amazon-bedrock): emit finish part after metadata event to preserve token usage in streaming#6160
jamesone wants to merge 2 commits into
Effect-TS:mainfrom
jamesone:fix/ai-bedrock-streaming-cached-tokens

Conversation

@jamesone

@jamesone jamesone commented Apr 8, 2026

Copy link
Copy Markdown

Type

  • Bug Fix

Description

In the Bedrock ConverseStream API, events arrive in the order: messageStopmetadata. The metadata event carries all token usage data (inputTokens, outputTokens, totalTokens, cacheReadInputTokens, cacheWriteInputTokens) as well as trace information.

Previously, the streaming handler emitted the finish part during the messageStop event, before the metadata event had populated the usage object. Because the downstream LanguageModel layer decodes stream parts through a schema (creating new instances), the finish part was captured with uninitialized usage values — causing all token counts (including cachedInputTokens) to be lost in streaming responses.

Fix

The fix introduces a tryEmitFinish guard that defers the finish part until both messageStop (which provides the stop reason) and metadata (which provides usage/trace) have been received. This:

  • Ensures cachedInputTokens, inputTokens, outputTokens, totalTokens are all correctly populated in streaming responses
  • Ensures trace and cacheWriteInputTokens metadata are present
  • Handles event ordering defensively (emits on whichever arrives second)
  • Preserves correct behavior when errors interrupt the stream between messageStop and metadata (no misleading finish part with empty usage)

The non-streaming (Converse) path was already correct since it reads directly from the decoded ConverseResponse.

Tests

Adds comprehensive test suite for AmazonBedrockLanguageModel covering both streaming and non-streaming paths:

  • Token usage population in the happy path
  • Cached token counts (cacheReadInputTokens / cacheWriteInputTokens)
  • Explicit zero cache counts preserved as 0 (not undefined)
  • Trace metadata propagation
  • Tool call content blocks with cached tokens
  • Error after messageStop (no misleading finish part)
  • Missing messageStop edge case (no finish part without a stop reason)
  • Stop reason mapping
  • Text part ordering relative to finish

Related

  • Closes #

…erve token usage in streaming

In the Bedrock ConverseStream API, events arrive in the order:
messageStop → metadata. The metadata event carries all token usage
data (inputTokens, outputTokens, totalTokens, cacheReadInputTokens,
cacheWriteInputTokens) as well as trace information.

Previously, the streaming handler emitted the finish part during the
messageStop event, before the metadata event had populated the usage
object. Because the downstream LanguageModel layer decodes stream
parts through a schema (creating new instances), the finish part was
captured with uninitialized usage values — causing all token counts
(including cachedInputTokens) to be lost in streaming responses.

The fix introduces a `tryEmitFinish` guard that defers the finish
part until both messageStop (which provides the stop reason) and
metadata (which provides usage/trace) have been received. This:

- Ensures cachedInputTokens, inputTokens, outputTokens, totalTokens
  are all correctly populated in streaming responses
- Ensures trace and cacheWriteInputTokens metadata are present
- Handles event ordering defensively (emits on whichever arrives
  second)
- Preserves correct behavior when errors interrupt the stream between
  messageStop and metadata (no misleading finish part with empty usage)

The non-streaming (Converse) path was already correct since it reads
directly from the decoded ConverseResponse.

Adds comprehensive test suite for AmazonBedrockLanguageModel covering
both streaming and non-streaming paths: token usage, cached tokens,
explicit zero cache counts, trace metadata, tool calls, error
scenarios, and missing event edge cases.
@jamesone
jamesone requested a review from IMax153 as a code owner April 8, 2026 01:52
@github-project-automation github-project-automation Bot moved this to Discussion Ongoing in PR Backlog Apr 8, 2026
@changeset-bot

changeset-bot Bot commented Apr 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6995efe

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@effect/ai-amazon-bedrock Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@IMax153

IMax153 commented Apr 9, 2026

Copy link
Copy Markdown
Member

@jamesone - I think this PR needs a pnpm lint-fix to fixup the linting issues.

@IMax153

IMax153 commented Apr 17, 2026

Copy link
Copy Markdown
Member

@loklaan - I'm not sure what changes were made but CI is failing. Looks like it might have to do with changes made to the lockfile.

@loklaan

loklaan commented Jun 1, 2026

Copy link
Copy Markdown

Woops missed that ping from Maxwell - @jamesone I think it was intended for you 🙇 gl

@fubhy

fubhy commented Jul 9, 2026

Copy link
Copy Markdown
Member

Thanks for the PR. CI is currently failing; could you please update the branch and address the failing checks, or confirm whether this is still active?

@fubhy

fubhy commented Jul 9, 2026

Copy link
Copy Markdown
Member

Thanks for the PR. The core Bedrock streaming finish/metadata fix appears to already be present on current main, and this branch is now conflicting with failing CI. I’m going to close this out; if there is remaining test coverage or behavior not covered by main, please open a fresh PR against current main.

@fubhy fubhy closed this Jul 9, 2026
@github-project-automation github-project-automation Bot moved this from Discussion Ongoing to Done in PR Backlog Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

4 participants